package come.bowen.mypet;

import javax.imageio.ImageIO;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

public class DesktopPetSpeed extends JFrame {

    // --- 素材区 ---
    private Image imgNormal;
    private Image imgAngry;
    // private Image imgShy;

    private boolean isAngry = false;
    private String bubbleText = null;

    private JTextField inputField;
    private JPanel mainPanel;
    private Timer bubbleTimer;

    private static final int PET_WIDTH = 280;
    private static final int PET_HEIGHT = 420;
    private static final int WIN_WIDTH = 300;
    private static final int WIN_HEIGHT = 550;

    private Point initialClick;

    public DesktopPetSpeed() {
        loadImages();
        initFrame();
        initPanel();
        initInputField();
        setVisible(true);
        speak("主人，我已经调整好语速啦！");
        // 启动时多显示一会，5秒
        showBubble("主人，我已经调整好语速啦！", false, 5000);
    }

    private void initFrame() {
        setUndecorated(true);
        setBackground(new Color(0, 0, 0, 0));
        setAlwaysOnTop(true);
        setType(Type.UTILITY);
        setSize(WIN_WIDTH, WIN_HEIGHT);
        setLocation(400, 200);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    private void initPanel() {
        mainPanel = new JPanel() {
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                Graphics2D g2d = (Graphics2D) g;
                g2d.setBackground(new Color(0, 0, 0, 0));
                g2d.clearRect(0, 0, getWidth(), getHeight());
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

                Image currentImg = isAngry ? imgAngry : imgNormal;
                if (currentImg != null) {
                    g2d.drawImage(currentImg, 10, 80, PET_WIDTH, PET_HEIGHT, this);
                }

                if (bubbleText != null) {
                    drawBubble(g2d);
                }
            }
        };

        mainPanel.setLayout(null);
        mainPanel.setOpaque(false);
        this.setContentPane(mainPanel);

        MouseAdapter ma = new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) { initialClick = e.getPoint(); }
            @Override
            public void mouseDragged(MouseEvent e) {
                if (initialClick == null) return;
                int xMoved = e.getX() - initialClick.x;
                int yMoved = e.getY() - initialClick.y;
                setLocation(getLocation().x + xMoved, getLocation().y + yMoved);
            }
            @Override
            public void mouseClicked(MouseEvent e) {
                if (e.getButton() == MouseEvent.BUTTON3) {
                    speak("休息啦，拜拜~");
                    try { Thread.sleep(1000); } catch (Exception ex) {}
                    System.exit(0);
                }
                if (e.getButton() == MouseEvent.BUTTON1) {
                    // 点击时的气泡也延长到 3秒
                    showBubble("是想试试音效吗？", true, 3000);
                    speak("喂喂喂，听得见吗？");
                }
            }
        };
        mainPanel.addMouseListener(ma);
        mainPanel.addMouseMotionListener(ma);
    }

    private void showBubble(String text, boolean angryState, int duration) {
        if (bubbleTimer != null && bubbleTimer.isRunning()) bubbleTimer.stop();

        this.bubbleText = text;
        this.isAngry = angryState;
        mainPanel.repaint();

        // 如果 duration 是 0，就一直显示（直到下一次刷新）
        if (duration > 0) {
            bubbleTimer = new Timer(duration, e -> {
                this.bubbleText = null;
                this.isAngry = false;
                mainPanel.repaint();
            });
            bubbleTimer.setRepeats(false);
            bubbleTimer.start();
        }
    }

    private void drawBubble(Graphics2D g) {
        if (bubbleText == null) return;
        int charPerLine = 13;
        List<String> lines = new ArrayList<>();
        for (int i = 0; i < bubbleText.length(); i += charPerLine) {
            int end = Math.min(i + charPerLine, bubbleText.length());
            lines.add(bubbleText.substring(i, end));
        }
        int lineHeight = 20;
        int bubbleHeight = 40 + (lines.size() * lineHeight);

        g.setColor(new Color(255, 255, 255, 240));
        g.fillRoundRect(10, 0, PET_WIDTH, bubbleHeight, 20, 20);
        g.setColor(new Color(100, 149, 237));
        g.setStroke(new BasicStroke(3));
        g.drawRoundRect(10, 0, PET_WIDTH, bubbleHeight, 20, 20);

        int[] xPoints = {PET_WIDTH/2, PET_WIDTH/2 + 20, PET_WIDTH/2 + 10};
        int[] yPoints = {bubbleHeight, bubbleHeight, bubbleHeight + 15};
        g.setColor(new Color(255, 255, 255, 240));
        g.fillPolygon(xPoints, yPoints, 3);
        g.setColor(new Color(100, 149, 237));
        g.drawPolyline(xPoints, yPoints, 3);

        g.setColor(Color.BLACK);
        g.setFont(new Font("微软雅黑", Font.BOLD, 14));
        int textY = 30;
        for (String line : lines) {
            g.drawString(line, 20, textY);
            textY += lineHeight;
        }
    }

    private void initInputField() {
        inputField = new JTextField();
        inputField.setBounds(10, 80 + PET_HEIGHT + 5, PET_WIDTH, 30);
        inputField.setOpaque(false);
        inputField.setForeground(Color.CYAN);
        inputField.setFont(new Font("微软雅黑", Font.BOLD, 14));
        inputField.setBorder(BorderFactory.createLineBorder(new Color(255, 255, 255, 100)));

        inputField.addActionListener(e -> {
            String text = inputField.getText();
            if (!text.isEmpty()) {
                inputField.setText("");
                // 思考状态，时间设为 0 (不自动消失，直到收到回复)
                showBubble("思考中...", true, 0);

                AIService.chat(text, reply -> {
                    // --- 【优化重点】阅读时间算法 ---
                    // 基础 5000毫秒(5秒) + 每个字 300毫秒
                    // 例如 10个字，就是 5s + 3s = 8s，足够慢慢看了！
                    int readTime = 5000 + (reply.length() * 300);
                    showBubble(reply, false, readTime);
                    speak(reply);
                });
            }
        });
        mainPanel.add(inputField);
    }

    private void loadImages() {
        try {
            imgNormal = ImageIO.read(new File("F:\\MyTablePet\\pet1.png"));
            imgAngry = ImageIO.read(new File("F:\\MyTablePet\\pet2.png"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // --- 极速版核心修复：强制转码为 Java 喜欢的格式 ---
    private void speak(String text) {
        new Thread(() -> {
            try {
                System.out.println("--- [语音合成] 开始: " + text + " ---");

                ProcessBuilder pb = new ProcessBuilder("python", "F:\\MyTablePet\\step1_tts.py", text);
                pb.redirectErrorStream(true);
                pb.environment().put("PYTHONIOENCODING", "utf-8");
                Process p = pb.start();
                p.waitFor();

                File mp3File = new File("F:\\MyTablePet\\temp_raw.mp3");
                File wavFile = new File("F:\\MyTablePet\\temp_speed.wav");

                if (!mp3File.exists() || mp3File.length() < 100) {
                    System.err.println("【错误】MP3 文件生成失败！");
                    return;
                }

                // 查找 ffmpeg
                String ffmpegCmd = "ffmpeg";
                File rvcFFmpeg = new File("F:\\RVC\\ffmpeg.exe");
                if (!isFFmpegAvailable() && rvcFFmpeg.exists()) {
                    ffmpegCmd = rvcFFmpeg.getAbsolutePath();
                }

                ProcessBuilder pbConvert = new ProcessBuilder(ffmpegCmd, "-y", "-i", mp3File.getAbsolutePath(),
                        "-acodec", "pcm_s16le",
                        "-ar", "44100",
                        "-ac", "1",
                        wavFile.getAbsolutePath());

                pbConvert.redirectErrorStream(true);
                Process pConvert = pbConvert.start();

                try (BufferedReader r = new BufferedReader(new InputStreamReader(pConvert.getInputStream()))) {
                    while (r.readLine() != null) {}
                }
                int exitCode = pConvert.waitFor();

                if (wavFile.exists() && exitCode == 0) {
                    playWav(wavFile);
                } else {
                    // 转码失败兜底
                    Desktop.getDesktop().open(mp3File);
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start();
    }

    private boolean isFFmpegAvailable() {
        try {
            Runtime.getRuntime().exec("ffmpeg -version").waitFor();
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    private void playWav(File file) {
        try (AudioInputStream audioStream = AudioSystem.getAudioInputStream(file)) {
            Clip clip = AudioSystem.getClip();
            clip.open(audioStream);
            clip.start();
            long microSeconds = clip.getMicrosecondLength();
            Thread.sleep(microSeconds / 1000 + 200);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            System.setProperty("sun.java2d.opengl", "true");
            new DesktopPetSpeed();
        });
    }
}